package erros

import (
	"fmt"
	"runtime"
)

// Error is a custom error type.
type Error struct {
	Code  int
	Msg   string
	Stack []byte `json:"stack,omitempty"`
}

func New(code int, format string, args ...any) *Error {
	msg := fmt.Sprintf(format, args...)
	codeMsg, ok := CodeStrMap[code]
	if ok {
		if msg == "" {
			msg = codeMsg
		} else {
			msg = codeMsg + ", " + msg
		}
	}
	return &Error{Code: code, Msg: msg}
}

func (e *Error) Error() string {
	if e != nil {
		return e.Msg
	}
	return "<nil>"
}

func (e *Error) WithStackTrace(all bool) *Error {
	stackTrace := make([]byte, 2048)
	runtime.Stack(stackTrace, all)
	e.Stack = stackTrace
	return e
}

func (e *Error) WithMsgf(format string, args ...any) *Error {
	e.Msg = fmt.Sprintf(format, args...)
	return e
}

func (e *Error) String() string {
	if e != nil {
		return fmt.Sprintf("error code: %d, msg: %s", e.Code, e.Msg)
	}
	return "nil"
}
